# Generic Makefile for C/C++ Program

##==========================================================================
## 需要调整的项
##==========================================================================

# 编译模式: Debug, Release 
MODE = Release

# 预处理选项
CPPFLAGS = 

# 链接选项
LDFLAGS =

# 需要额外添加的库
LIBS =

# 源文件目录
SRC_DIRS =

# 可执行文件名称
APP =

##==========================================================================
## 不常修改的项
##==========================================================================

# 源文件后缀名
SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp

# 头文件后缀名
HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp

# 编译选项: -pg 生成性能测试报表; -coverage 生成代码覆盖报表
CFLAGS = -O2 -Wall
CXXFLAGS = $(CFLAGS)

# 调试选项 -g, -g2, -g3
DEBUG_FLAG = -g

# std flag Options: -std=c99,-std=iso9899:199409, -std=c89
STD_FLAG =

# The C program compiler.
CC = icc

# The C++ program compiler.
CXX = icpc

# 打开此选项后以C++格式编译C程序
#CC = $(CXX)

# 删除文件的命令
RM = rm -f

# ctags命令及选项
CTAGS = ctags
CTAGSFLAGS =--c++-kinds=+p --fields=+iaS --extra=+q  

##==========================================================================
# 对未指定选项做一些处理
##==========================================================================

#-设置可执行文件名-#
EMPTY =
SPACE = $(EMPTY) $(EMPTY)
ifeq ($(APP),)
    CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))
    APP = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))
    ifeq ($(APP),)
	APP = a.out
    endif
endif
ifeq ($(OS),Windows_NT)
    APP := $(APP).exe
endif

#-DEBUG模式下添加选项-#
ifeq ($(MODE),Debug)
    CFLAGS += $(DEBUG_FLAG)
endif

#-源文件目录-#
ifeq ($(SRC_DIRS),)
    SRC_DIRS = .
endif

#-添加std选项-#
ifneq ($(STD_FLAG),)
    CFLAGS += $(STD_FLAG)
endif

##==========================================================================
# 下面的基本不要修改，自动化执行
##==========================================================================

# foreach 对每一个后缀名做wildcard（展开通配符得到实际的源文件）处理 
SOURCES = $(foreach d,$(SRC_DIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
HEADERS = $(foreach d,$(SRC_DIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))
SRC_CXX = $(filter-out %.c,$(SOURCES))
OBJS = $(addsuffix .o, $(basename $(SOURCES)))

COMPILE_c = $(CC) $(CPPFLAGS) $(CFLAGS) -c
COMPILE_cxx = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c
LINK_c = $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
LINK_cxx = $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS)
PRODUCTS = $(APP) $(OBJS) tags gmon.out *.gcov *.gcda *.gcno

#==================================================================
.PHONY: all objs ctags clean distclean garbageclean rebuild help show

# Delete the default suffixes
.SUFFIXES:

all: $(APP)
 
# 生成目标文件(.o).
objs:$(OBJS)

%.o:%.c
	$(COMPILE_c) $< -o $@
%.o:%.C
	$(COMPILE_cxx) $< -o $@
%.o:%.cc
	$(COMPILE_cxx) $< -o $@
%.o:%.cpp
	$(COMPILE_cxx) $< -o $@
%.o:%.CPP
	$(COMPILE_cxx) $< -o $@
%.o:%.c++
	$(COMPILE_cxx) $< -o $@
%.o:%.cp
	$(COMPILE_cxx) $< -o $@
%.o:%.cxx
	$(COMPILE_cxx) $< -o $@

# 生成ctags
ctags: $(HEADERS) $(SOURCES)
	$(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES)

# 链接成可执行文件
$(APP):$(OBJS)
ifeq ($(SRC_CXX),) # C program
	$(LINK_c) $(OBJS) -o $@
	@echo
	@echo Type ./$@ to execute the program.
else # C++ program
	$(LINK_cxx) $(OBJS) -o $@
	@echo
	@echo Type ./$@ to execute the program.
endif

clean:
	$(RM) $(OBJS) $(APP)

distclean:
	$(RM) $(PRODUCTS)

garbageclean:
	$(RM) *.save 

rebuild: clean all 

excute:
	@time ./$(APP)
help:
	@echo
	@echo 'Usage: make [TARGET]'
	@echo 'TARGETS:'
	@echo ' all (=make) compile and link.'
	@echo ' objs compile only (no linking).'
	@echo ' ctags create ctags for VI editor.'
	@echo ' clean clean objects and the executable file.'
	@echo ' distclean clean objects and executable .'
	@echo ' garbageclean clean some garbage.'
	@echo ' excute excute the program.'
	@echo ' rebuild clean and make all again.'
	@echo ' show show variables (for debug use only).'
	@echo ' help print this message.'
	@echo

show:
	@echo 'OS :' $(OS)
	@echo 'APP :' $(APP)
	@echo 'MODE :' $(MODE)
	@echo 'SRC_DIRS :' $(SRC_DIRS)
	@echo 'HEADERS :' $(HEADERS)
	@echo 'SOURCES :' $(SOURCES)
	@echo 'SRC_CXX :' $(SRC_CXX)
	@echo 'OBJS :' $(OBJS)
	@echo 'COMPILE_c :' $(COMPILE_c)
	@echo 'COMPILE_cxx :' $(COMPILE_cxx)
	@echo 'LINK_c :' $(LINK_c)
	@echo 'LINK_cxx :' $(LINK_cxx)
	@echo 'PRODUCTS :' $(PRODUCTS)
